package com.mlethe.library.recyclerview.adapter;

import android.graphics.Canvas;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import com.mlethe.library.recyclerview.listener.OnItemDragListener;
import com.mlethe.library.recyclerview.listener.OnItemSwipeListener;
import com.mlethe.library.recyclerview.viewholder.ViewHolder;

import java.util.List;

/**
 * item 滑动删除和拖拽
 * <p>
 * 使用方式:
 * ItemTouchHelper mItemHelper = new ItemTouchHelper(new ItemDragAndSwipeCallback(new BaseDraggableAdapter());
 * mItemHelper.attachToRecyclerView(recyclerView);
 *
 * @author Mlethe
 * @date 2020/9/19
 */
public abstract class BaseDraggableAdapter<T, VH extends ViewHolder> extends UniversalAdapter<T, ViewHolder> {

    private OnItemDragListener<T> mOnItemDragListener;
    private OnItemSwipeListener<T> mOnItemSwipeListener;

    protected boolean itemDragEnabled = false;
    protected boolean itemSwipeEnabled = false;

    private T mSwipeItem;

    public BaseDraggableAdapter() {
    }

    public BaseDraggableAdapter(List<T> data) {
        super(data);
    }

    public BaseDraggableAdapter(int layoutId) {
        super(layoutId);
    }

    public BaseDraggableAdapter(List<T> data, int layoutId) {
        super(data, layoutId);
    }

    /**
     * 开始拖拽
     *
     * @param viewHolder viewHolder
     */
    public void onItemDragStart(@NonNull RecyclerView.ViewHolder viewHolder) {
        if (!itemDragEnabled) {
            return;
        }
        if (mOnItemDragListener != null) {
            int position = getViewHolderPosition(viewHolder);
            mOnItemDragListener.onItemDragStart((ViewHolder) viewHolder, getItem(position), position);
        }
    }

    /**
     * 正在拖拽
     *
     * @param recyclerView recyclerView
     * @param source       source
     * @param fromPos      fromPos
     * @param target       target
     * @param toPos        toPos
     */
    public void onItemDragMoving(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder source, int fromPos, @NonNull RecyclerView.ViewHolder target, int toPos) {
        if (!itemDragEnabled) {
            return;
        }
        int headerCount = getHeaderCount();
        int from = fromPos - headerCount;
        int to = toPos - headerCount;
        T item = getItem(from);
        if (from != to && inRange(from) && inRange(to)) {
            moveItem(from, to);
            notifyItemMoved(fromPos, toPos);
            int startPosition = fromPos < toPos ? fromPos : toPos + 1;
            int changeCount = Math.abs(toPos - fromPos);
            notifyItemRangeChanged(startPosition, changeCount);
        }
        if (mOnItemDragListener != null) {
            mOnItemDragListener.onItemDragMoving((ViewHolder) source, from, (ViewHolder) target, to, item);
        }
    }

    /**
     * 拖拽结束
     *
     * @param viewHolder viewHolder
     */
    public void onItemDragEnd(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
        if (!itemDragEnabled) {
            return;
        }
        int position = viewHolder.getBindingAdapterPosition();
        recyclerView.post(() -> {
            // 使用post防止出现 Cannot call this method while RecyclerView is computing a layout or scrolling 错误
            notifyItemChanged(position);
        });
        if (mOnItemDragListener != null) {
            int realPos = position - getHeaderCount();
            mOnItemDragListener.onItemDragEnd((ViewHolder) viewHolder, getItem(realPos), realPos);
        }
    }

    /**
     * swipe 开始滑动
     *
     * @param viewHolder viewHolder
     */
    public void onItemSwipeStart(@NonNull RecyclerView.ViewHolder viewHolder) {
        if (!itemSwipeEnabled) {
            return;
        }
        if (mOnItemSwipeListener != null) {
            int position = getViewHolderPosition(viewHolder);
            mOnItemSwipeListener.onItemSwipeStart((ViewHolder) viewHolder, getItem(position), position);
        }
    }

    /**
     * swipe 滑动中
     *
     * @param canvas            canvas
     * @param viewHolder        viewHolder
     * @param dX                X轴移动的距离
     * @param dY                Y轴移动的距离
     * @param isCurrentlyActive 如果当前被用户操作为true，反之为false
     */
    public void onItemSwiping(@NonNull Canvas canvas, @NonNull RecyclerView.ViewHolder viewHolder, float dX, float dY, boolean isCurrentlyActive) {
        if (!itemSwipeEnabled) {
            return;
        }
        if (mOnItemSwipeListener != null) {
            mOnItemSwipeListener.onItemSwipeMoving(canvas, (ViewHolder) viewHolder, dX, dY, isCurrentlyActive);
        }
    }

    /**
     * swipe 到达滑动消失的距离
     *
     * @param viewHolder viewHolder
     */
    public void onItemSwiped(@NonNull RecyclerView.ViewHolder viewHolder) {
        if (!itemSwipeEnabled) {
            return;
        }
        int position = getViewHolderPosition(viewHolder);
        if (inRange(position)) {
            T item = getItem(position);
            mSwipeItem = item;
            notifyItemRemove(position);
            if (mOnItemSwipeListener != null) {
                mOnItemSwipeListener.onItemSwiped((ViewHolder) viewHolder, item, position);
            }
        }
    }

    /**
     * @param viewHolder viewHolder
     */
    public void onItemSwipeClear(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
        T item = mSwipeItem;
        mSwipeItem = null;
        if (mOnItemSwipeListener != null && itemSwipeEnabled) {
            mOnItemSwipeListener.onItemSwipeClear((ViewHolder) viewHolder, item, getViewHolderPosition(viewHolder));
        }
    }

    public boolean isItemDragEnabled() {
        return itemDragEnabled;
    }

    public boolean isItemSwipeEnabled() {
        return itemSwipeEnabled;
    }

    /**
     * 开启拖拽
     *
     * @return BaseDraggableAdapter<T, VH>
     */
    public BaseDraggableAdapter<T, VH> enableDragItem() {
        itemDragEnabled = true;
        return this;
    }

    /**
     * 取消拖拽
     *
     * @return BaseDraggableAdapter<T, VH>
     */
    public BaseDraggableAdapter<T, VH> disableDragItem() {
        itemDragEnabled = false;
        return this;
    }

    /**
     * 开启滑动删除
     *
     * @return BaseDraggableAdapter<T, VH>
     */
    public BaseDraggableAdapter<T, VH> enableSwipeItem() {
        itemSwipeEnabled = true;
        return this;
    }

    /**
     * 取消滑动删除
     *
     * @return BaseDraggableAdapter<T, VH>
     */
    public BaseDraggableAdapter<T, VH> disableSwipeItem() {
        itemSwipeEnabled = false;
        return this;
    }

    /**
     * 设置拖拽监听
     *
     * @param listener 拖拽监听
     * @return BaseDraggableAdapter<T, VH>
     */
    public BaseDraggableAdapter<T, VH> setOnItemDragListener(OnItemDragListener<T> listener) {
        this.mOnItemDragListener = listener;
        return this;
    }

    /**
     * 设置滑动删除监听
     *
     * @param listener 滑动删除监听
     * @return BaseDraggableAdapter<T, VH>
     */
    public BaseDraggableAdapter<T, VH> setOnItemSwipeListener(OnItemSwipeListener<T> listener) {
        this.mOnItemSwipeListener = listener;
        return this;
    }
}
